<template>
  <div class="data-detail">
    <div class="header-bar">
      <el-button @click="router.back()" type="primary" size="small"
        >返回</el-button
      >
      <span class="title">数据详情查看</span>
      <div class="data-info" v-if="detailData.dataId">
        <el-tag size="small" type="info">ID: {{ detailData.dataId }}</el-tag>
        <el-tag size="small" type="success">{{ detailData.startCollectTime }}</el-tag>
        <el-tag size="small" type="warning">{{ detailData.collectDuration }}</el-tag>
        <el-tag size="small" :type="detailData.isArchived === '1' ? 'success' : 'info'">
          {{ detailData.isArchived === '1' ? '已归档' : '未归档' }}
        </el-tag>
      </div>
    </div>
    <div class="detail-content-area" v-loading="loading" style="display: flex; flex-direction: column; height: calc(100vh - 60px);">
      <!-- 视频模块：与TaskDetail.vue一致 -->
      <div class="video-toolbar">
        <div class="toolbar-left">
          <el-button
            @click="enlargeSelectedVideos"
            :disabled="selectedVideos.length === 0"
            type="primary"
            size="small"
          >
            <el-icon><ZoomIn /></el-icon>
            放大选中视频 ({{ selectedVideos.length }})
          </el-button>
          <el-button @click="selectAllVideos" size="small">
            {{ selectedVideos.length === localFiles.videos.length ? "取消全选" : "全选" }}
          </el-button>
        </div>
        <div class="toolbar-right">
          <span class="toolbar-label">窗口布局</span>
          <el-select
            v-model="windowLayout"
            size="small"
            style="width: 120px"
            @change="refreshGrid"
          >
            <el-option label="每行2路" value="2" />
            <el-option label="每行3路" value="3" />
            <el-option label="每行4路" value="4" />
          </el-select>
        </div>
      </div>
      <div class="video-scroll-wrapper" style="flex: 1; overflow-y: auto;">
        <div v-if="localFiles.videos.length === 0" class="no-videos">
          <el-empty description="暂无视频文件" :image-size="80">
            <template #description>
              <div class="empty-content">
                <p class="empty-title">未找到视频文件</p>
                <p class="empty-tip">请检查存储路径: {{ detailData.storagePath }}</p>
              </div>
            </template>
          </el-empty>
        </div>
        <div v-else class="video-grid" :style="gridStyle">
          <div
            v-for="(video, index) in localFiles.videos"
            :key="index"
            class="video-card"
            :class="{ selected: selectedVideos.includes(index) }"
          >
            <div class="video-card-topbar">
              <el-tooltip :content="video.fileName" placement="top" :show-after="500">
                <span class="video-title">{{ video.fileName }}</span>
              </el-tooltip>
            </div>
            <div class="video-card-icons">
              <el-tooltip content="最大化" placement="top">
                <el-icon class="video-icon" @click.stop="maximizeVideo(index)">
                  <FullScreen />
                </el-icon>
              </el-tooltip>
            </div>
            <div class="video-card-body">
              <VideoPlayer
                :ref="(el) => (videoRefs[index] = el)"
                :video-src="getVideoPath(videoPath+video.accessPath)"
                :poster="getVideoPoster(index)"
                :disabled="videoStatus[index] !== 'online'"
                :hide-controls="true"
                :disable-click="false"
                :current-time="currentPlaybackTime"
                :is-playing="isPlaying"
                @timeupdate="onVideoTimeUpdate"
                @loadedmetadata="onVideoLoaded(index)"
                @ended="onVideoEnded"
              />

              <!-- 视频选择复选框 -->
              <div class="video-checkbox">
                <el-checkbox
                  v-model="selectedVideos"
                  :value="index"
                  @change="onVideoSelect"
                />
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- 遥测文件选择 -->
      <div v-if="telemetryFiles.length > 0 && showTelemetrySelection" class="file-selection-section">
        <div class="section-header">
            <h3>{{ detailData.collectionTaskId }}-{{ detailData.collectionTaskName }}遥测文件选择</h3>
            <div style="display: flex; align-items: right;">
                <span style="margin-left: 20px">显示频率：</span>
                <el-select v-model="displayFrequency" size="small" style="margin-left: 10px; width: 100px;" @change="onFrequencyChange">
                  <el-option label="原始频率" :value="0" />
                  <el-option label="0.5秒" :value="500" />
                  <el-option label="1秒" :value="1000" />
                  <el-option label="2秒" :value="2000" />
                  <el-option label="5秒" :value="5000" />
                  <el-option label="10秒" :value="10000" />
                </el-select>
            </div>            
            <span class="file-count" style="margin-left: 20px;">共 {{ telemetryFiles.length }} 个文件，已选择 {{ selectedTelemetryFiles.length }} 个</span>
        </div>
        <div class="data-grid telemetry-files" style="max-height: 300px; overflow-y: auto;">
          <div
              v-for="file in telemetryFiles"
              :key="file.fileName"
              class="data-card"
              :class="{ 'selected': selectedTelemetryFiles.includes(file.fileName) }"
              @click="toggleTelemetryFileSelection(file.fileName)"
          >
            <!-- 复选框 -->
            <div class="card-checkbox">
              <input
                  type="checkbox"
                  :id="`telemetry-${file.fileName}`"
                  :checked="selectedTelemetryFiles.includes(file.fileName)"
                  @change="(e) => {
                    e.stopPropagation();
                    toggleTelemetryFileSelection(file.fileName);
                  }"
              >
              <label :for="`telemetry-${file.fileName}`" class="custom-checkbox"></label>
            </div>

            <!-- 数据内容 -->
            <div class="card-content">
              <h3 class="data-name">{{ file.fileName }}</h3>
              <p class="file-size">{{ file.fileSize}} KB</p>
            </div>
          </div>
        </div>
      </div>

      <!-- 遥测数据图表 - 每个选中文件对应一个图表 -->
      <div v-if="showTelemetryCharts" class="chart-section" style="flex: 1; overflow-y: auto;">
        <div class="section-header">
          <h3>{{ detailData.collectionTaskId }}-{{ detailData.collectionTaskName }}遥测数据图表</h3>
          <span style="margin-left: 20px">显示频率：{{ displayFrequency === 0 ? '原始频率' : displayFrequency / 1000 + '秒' }}</span>
          <div class="chart-info">
            <span style="margin-left: 20px">共显示 {{ selectedTelemetryFiles.length }} 个文件的图表</span>
            <el-button @click="reselectTelemetryFiles" size="small" type="primary" style="margin-left: 20px">
              重新选择
            </el-button>
          </div>
        </div>
        <div class="chart-grid scroll-wrapper" :style="chartGridStyle">
          <div v-for="fileName in selectedTelemetryFiles" :key="fileName" class="chart-item">
            <div class="chart-item-header">
              <span class="chart-file-name">{{ fileName }}</span>
              <div class="header-right">
                <span class="chart-data-count">数据点：{{ telemetryDataByFile[fileName]?.length || 0 }} 个</span>
                <el-button 
                  size="small" 
                  type="primary" 
                  plain 
                  @click="downloadChartImage(fileName)"
                  style="margin-left: 10px;"
                >
                  <i class="el-icon-download"></i> 下载
                </el-button>
              </div>
            </div>
            <div v-if="telemetryDataByFile[fileName] && telemetryDataByFile[fileName].length > 0" class="chart-container" :data-chart-file="fileName">
              <HistoricalChart
                :historical-data="telemetryDataByFile[fileName]"
                :total-duration="totalPlaybackTime"
                :is-playing="isPlaying"
                :current-playback-time="calculateChartPlaybackTime()"
                :ref="el => historicalChartRefs[fileName] = el"
                @time-change="onChartTimeChange"
                @playback-complete="onTelemetryPlaybackComplete"
              />
            </div>
            <div v-else class="no-telemetry">
              <el-empty description="文件无有效数据" :image-size="40">
              </el-empty>
            </div>
          </div>
        </div>
      </div>

      <!-- 播放控制区域 -->
      <div class="playback-section" v-if="localFiles.videos.length > 0">
        <div class="playback-controls">
          <div class="control-left">
            <span class="current-time">{{
              formatCombinedTime(detailData.startCollectTime, currentPlaybackTime)
            }}</span>
            <el-button
              :icon="isPlaying ? VideoPause : VideoPlay"
              @click="togglePlayback"
              size="default"
              circle
              class="play-btn"
              :disabled="!isTimeValid()"
            />
            <el-button @click="seekBackward" size="small" circle>
              <el-icon><DArrowLeft /></el-icon>
            </el-button>
            <el-button @click="seekForward" size="small" circle>
              <el-icon><DArrowRight /></el-icon>
            </el-button>
          </div>
          <div class="progress-container">
            <el-slider
              v-model="playbackProgress"
              :max="100"
              @change="onProgressChange"
              @input="onProgressInput"
              :show-tooltip="false"
              class="progress-slider"
            />
          </div>
          <div class="control-right">
            <span class="total-time">{{
              formatTimeOnly(detailData.endCollectTime)
            }}</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 放大视频弹窗 -->
    <el-dialog
      v-model="showEnlargedDialog"
      title="多路视频放大显示"
      :fullscreen="true"
      :show-close="true"
      :close-on-click-modal="false"
      :close-on-press-escape="true"
      :before-close="closeEnlargedDialog"
      class="enlarged-video-dialog fullscreen-dialog"
    >
      <template #header>
        <div class="fullscreen-header">
          <span class="dialog-title">多路视频放大显示</span>
        </div>
      </template>

      <div class="enlarged-video-container">
        <div
          class="enlarged-video-grid"
          :style="enlargedGridStyle"
          :class="enlargedGridClass"
        >
          <div
            v-for="videoIndex in selectedVideos"
            :key="videoIndex"
            class="enlarged-video-item"
            :class="enlargedItemClass"
          >
            <div class="enlarged-video-header">
              <el-tooltip :content="getVideoTitle(videoIndex)" placement="top" :show-after="500">
                <span>{{ getVideoTitle(videoIndex) }}</span>
              </el-tooltip>
            </div>
            <VideoPlayer
              :ref="(el) => (enlargedVideoRefs[videoIndex] = el)"
              :video-src="getVideoSrcForIndex(videoIndex)"
              :poster="getVideoPoster(videoIndex)"
              :current-time="currentPlaybackTime"
              :is-playing="isPlaying"
              :playback-speed="playbackSpeed"
              :hide-controls="true"
              :disable-click="true"
              @timeupdate="onVideoTimeUpdate"
              @loadedmetadata="onVideoLoaded(videoIndex)"
              @ended="onVideoEnded"
            />
          </div>
        </div>

        <!-- 弹窗内的统一播放控制条 -->
        <div class="enlarged-playback-controls">
          <div class="enlarged-control-left">
            <span class="current-time">{{
              formatPlaybackTime(currentPlaybackTime)
            }}</span>
            <el-button
              :icon="isPlaying ? VideoPause : VideoPlay"
              @click="togglePlayback"
              size="small"
              circle
              class="play-btn"
              :disabled="!isTimeValid()"
            />
            <el-button @click="seekBackward" size="small" circle>
              <el-icon><DArrowLeft /></el-icon>
            </el-button>
            <el-button @click="seekForward" size="small" circle>
              <el-icon><DArrowRight /></el-icon>
            </el-button>
          </div>
          <div class="enlarged-progress-container">
            <el-slider
              v-model="playbackProgress"
              :max="100"
              @change="onProgressChange"
              @input="onProgressInput"
              :show-tooltip="false"
              class="progress-slider"
            />
          </div>
          <div class="enlarged-control-right">
            <span class="total-time">{{
              formatPlaybackTime(totalPlaybackTime)
            }}</span>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, watch, nextTick, onMounted } from "vue";
import { useRoute, useRouter } from "vue-router";
import {
  VideoPlay,
  VideoPause,
  FullScreen,
  ZoomIn,
  DArrowLeft,
  DArrowRight,
  Close,
  Refresh,
} from "@element-plus/icons-vue";
import HistoricalChart from "../components/charts/HistoricalChart.vue";
import VideoPlayer from "../components/VideoPlayer.vue";
import {API_CONFIG} from "../api";
import videoDataAPI from "../api/modules/videoData";
import telemetryDataListAPI from "../api/modules/telemetryDataList";
import {ElMessage} from "element-plus";

const route = useRoute();
const router = useRouter();
const id = route.params.id;
 const videoPath = ref(API_CONFIG.IMAGE_URL);
// 数据详情
const detailData = ref({});
const loading = ref(false);

// 计算总播放时长（毫秒）
const calculateTotalDuration = () => {
  if (!detailData.value.startCollectTime || !detailData.value.endCollectTime) {
    return 0;
  }
  
  const startTime = new Date(detailData.value.startCollectTime).getTime();
  const endTime = new Date(detailData.value.endCollectTime).getTime();
  
  if (isNaN(startTime) || isNaN(endTime) || endTime <= startTime) {
    return 0;
  }
  
  return endTime - startTime;
};

// 本地文件信息
const localFiles = ref({
  videos: [],
  telemetry: null,
  metadata: null
});

    // 检查开始时间和结束时间是否有效
    const isTimeValid = () => {
      return detailData.value.startCollectTime && detailData.value.endCollectTime && 
             !isNaN(new Date(detailData.value.startCollectTime).getTime()) && 
             !isNaN(new Date(detailData.value.endCollectTime).getTime());
    };

const getVideoPath = (accessPath) => {
  // 处理空格和特殊字符
  return `${accessPath}`
      .replace(/ /g, '%20')       // 空格转义
      .replace(/[^\x00-\x7F]/g, encodeURIComponent); // 中文编码
};
const getVideoList= async () => {
  loading.value = true;
  try {
    // 准备查询参数
    const params = {
      dataId: id,
    };
    const result = await videoDataAPI.getVideoList(params);
    console.log("获取视频列表结果:", result);
    if (result && result.code === 0) {
      localFiles.value.videos = result.data|| [];
      ElMessage.success(`加载了 ${  localFiles.value.videos.length} 条视频`);
    } else {
      throw new Error(result?.msg || '获取数据失败');
    }

  } catch (error) {
    console.error("加载数据失败:", error);
    ElMessage.error(`加载数据失败: ${error.message}`);
    localFiles.videos.value = [];
  } finally {
    loading.value = false;
  }
}
// 加载数据详情 - 从 sessionStorage 获取数据
const loadDataDetail = async () => {
  loading.value = true;
  try {
    // 从 sessionStorage 获取数据详情
    const storedData = sessionStorage.getItem('dataDetail');
    if (storedData) {
      detailData.value = JSON.parse(storedData);
      console.log("从 sessionStorage 获取的数据详情:", detailData.value);
    } else {
      // 如果没有数据，使用默认数据（用于测试）
      detailData.value = {
        dataId: id,
        startCollectTime: "2025-07-31 03:34:43",
        endCollectTime: "2025-07-31 03:35:43",
        collectDuration: "00:01:00",
        isArchived: "0",
        storagePath: "./collections/20250731_123312"
      };
      console.log("使用默认数据:", detailData.value);
    }

    // 根据存储路径加载本地文件
    await loadLocalFiles();
    
    // 计算并设置总播放时长（毫秒）
    const duration = calculateTotalDuration();
    if (duration > 0) {
      totalPlaybackTime.value = duration / 1000; // 转换为秒
    }
  } catch (error) {
    console.error("加载数据详情失败:", error);
  } finally {
    loading.value = false;
  }
};

// 根据存储路径加载本地文件
const loadLocalFiles = async () => {
  try {
    const storagePath = detailData.value.storagePath;
    if (!storagePath) {
      console.warn("存储路径为空");
      return;
    }

    console.log("正在加载存储路径:", storagePath);

    // 调用Electron API获取本地文件信息
    const result = await window.electronAPI.getCollectionFiles({
      storagePath: storagePath
    });
    console.log("获取本地文件信息结果:", result);
    if (result.success) {
      localFiles.value = result.files;
      console.log("本地文件信息:", localFiles.value);

      // 打印每个视频文件的完整路径
      localFiles.value.videos.forEach((video, index) => {
        console.log(`视频 ${index + 1}:`, {
          fileName: video.fileName,
          localPath: video.localPath,
          fileUrl: `file://${video.localPath}`
        });
      });
    } else {
      console.error("获取本地文件失败:", result.error);
    }
  } catch (error) {
    console.error("加载本地文件失败:", error);
  }
};

const windowLayout = ref(4);
const videoRefs = ref([]);
const enlargedVideoRefs = ref([]);
const videoStatus = ref([]);

// 根据视频数量初始化状态
const initializeVideoStatus = () => {
  const videoCount = localFiles.value.videos.length;
  videoStatus.value = Array(videoCount).fill("online");
};
const currentPlaybackTime = ref(0);
const totalPlaybackTime = ref(0); // 初始化为0，等待视频加载后更新
const playbackProgress = ref(0);
const isPlaying = ref(false);
const playbackSpeed = ref(1);

// 新增：视频选择相关
const selectedVideos = ref([]);
const showEnlargedDialog = ref(false);

// 遥测数据 - 修改为按文件存储
const telemetryDataByFile = ref({});
// 遥测文件列表
const telemetryFiles = ref([]);
// 选中的遥测文件
const selectedTelemetryFiles = ref([]);
// 图表引用对象，存储所有选中文件的图表引用
const historicalChartRefs = ref({})

// 下载图表为图片 - 修复函数定义
const downloadChartImage = (fileName) => {
  try {
    // 获取组件实例
    const chartComponent = historicalChartRefs.value?.[fileName];
    let actualChart = null;
    
    // 优先尝试通过$refs.chartRef获取图表实例（根据日志发现存在这个引用）
    if (chartComponent && chartComponent.$refs && chartComponent.$refs.chartRef) {
      actualChart = chartComponent.$refs.chartRef;
    }
    
    // 如果找到图表实例并有getDataURL方法，尝试使用echarts原生方法导出
    if (actualChart && typeof actualChart.getDataURL === 'function') {
      const url = actualChart.getDataURL({
        type: 'png',
        pixelRatio: 2,
        backgroundColor: '#fff'
      });
      
      // 创建下载链接
      const link = document.createElement('a');
      link.download = `${fileName}_chart.png`;
      link.href = url;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      
      ElMessage.success('图表下载成功');
    } else {
      // 如果echarts方法不可用，使用备选方案 - 通过DOM获取图表canvas
      
      ElMessage.warning('图表尚未准备就绪或不支持下载功能，请稍候再尝试。');
    }
  } catch (error) {
    ElMessage.error('图表下载失败');
  }
}
// 控制是否显示遥测文件选择区域

// 计算图表播放时间（毫秒）- 基于startCollectTime的时间部分
const calculateChartPlaybackTime = () => {
  try {
    if (!detailData.value.startCollectTime) return 0;
    
    // 解析startCollectTime的时间部分（HH:mm:ss.SSS）
    const startTimeStr = detailData.value.startCollectTime;
    const timeMatch = startTimeStr.match(/\d{2}:\d{2}:\d{2}(\.\d{3})?/);
    
    if (timeMatch) {
      // 提取时间部分并确保格式为HH:mm:ss:SSS
      let timePart = timeMatch[0];
      if (timePart.includes('.')) {
        // 将HH:mm:ss.SSS转换为HH:mm:ss:SSS
        timePart = timePart.replace('.', ':');
      }
      
      // 解析时间格式：HH:mm:ss:SSS
      const [hours, minutes, seconds, milliseconds] = timePart.split(/[:.]/).map(Number);
      
      // 计算开始时间的毫秒数
      const startTimeMs = hours * 3600000 + minutes * 60000 + seconds * 1000 + (milliseconds || 0);
      
      // 加上当前播放时间（转换为毫秒）
      const resultMs = startTimeMs + Math.floor(currentPlaybackTime.value * 1000);
      
      console.log('计算的图表播放时间:', resultMs, 'ms (基于startCollectTime时间部分)');
      return resultMs;
    }
    
    return 0;
  } catch (error) {
    console.error('计算图表播放时间错误:', error);
    return 0;
  }
};
const showTelemetrySelection = ref(true);
// 控制是否显示遥测数据图表区域
const showTelemetryCharts = ref(false);

// 切换遥测文件选择
const toggleTelemetryFileSelection = (fileName) => {
  const index = selectedTelemetryFiles.value.indexOf(fileName);
  if (index > -1) {
    selectedTelemetryFiles.value.splice(index, 1);
  } else {
    selectedTelemetryFiles.value.push(fileName);
  }
};

// 注释掉自动监听，改为在播放按钮点击时触发
// watch(selectedTelemetryFiles, () => {
//   parseSelectedTelemetryFiles();
// });

// 显示频率（毫秒），默认为1秒
const displayFrequency = ref(1000);

// 根据显示频率过滤数据点的函数
const filterDataByFrequency = (data) => {
  if (!data || data.length === 0) return [];
  
  // 如果选择原始频率（值为0），直接返回原始数据，不进行过滤
  if (displayFrequency.value === 0) {
    console.log('选择原始频率，返回全部数据点，数量为:', data.length);
    return data;
  }
  
  const filteredData = [];
  let lastProcessedTime = -Infinity;
  
  data.forEach(point => {
    const currentTime = point.sysTime || 0;
    // 如果是第一个点，或者当前点与上一个处理的点时间差大于等于显示频率
    if (currentTime - lastProcessedTime >= displayFrequency.value) {
      filteredData.push(point);
      lastProcessedTime = currentTime;
    }
  });
  
  console.log(`按显示频率 ${displayFrequency.value}ms 过滤后，数据点数量从 ${data.length} 减少到 ${filteredData.length}`);
  return filteredData;
};

// 频率变化时重新解析数据
const onFrequencyChange = () => {
  console.log(`显示频率更改为: ${displayFrequency.value}ms`);
  // 重新解析数据
  parseSelectedTelemetryFiles();
};

// 解析选中的遥测文件内容 - 修改为异步函数，用于读取实际文件内容
const parseSelectedTelemetryFiles = async () => {
  // 清空现有数据
  telemetryDataByFile.value = {};
  
  // 为每个选中的文件单独解析数据
  for (const fileName of selectedTelemetryFiles.value) {
    const file = telemetryFiles.value.find(f => f.fileName === fileName);
    if (file) {
      try {
        // 构建完整的文件路径：API_CONFIG.IMAGE_URL + file.accessPath
        const filePath = file.accessPath || '';
        const serverAddress = API_CONFIG.IMAGE_URL;
        
        // 调用Electron API读取遥测文件内容
        const result = await window.electronAPI.readTelemetryFile({
          filePath: serverAddress+filePath
        });
        
        if (result.success && result.content) {
          const fileData = [];
          const fileContent = result.content;
          
          // 直接按行解析时间+值格式的文件
          const lines = fileContent.split('\n');
          let invalidLinesCount = 0;
          const totalNonEmptyLines = lines.filter(line => line.trim()).length;
          
          lines.forEach(line => {
            line = line.trim();
            if (line) {
              // 只接受时间+值格式的文件（如：16:04:26:713 0）
              const timeValueMatch = line.match(/^(\d{2}:\d{2}:\d{2}:\d{3})\s+(\d+\.?\d*)$/);
              if (timeValueMatch) {
                // 解析时间格式：HH:mm:ss:SSS
                const timeStr = timeValueMatch[1];
                const value = parseFloat(timeValueMatch[2]);
                
                // 提取文件名作为参数名（去掉.txt后缀）
                const paramName = fileName.replace('.txt', '');
                
                // 创建符合曲线图要求的数据格式 - 添加x和y属性
                const offset = convertTimeToOffset(timeStr);
                const dataPoint = {
                  sysTime: offset, // 使用相对于开始时间的偏移量（毫秒）
                  time: timeStr,
                  [paramName]: value,
                  x: timeStr,  // 使用时间作为x值
                  y: value     // 使用数据值作为y值
                };
                fileData.push(dataPoint);
              } else {
                // 不符合时间+值格式的行
                invalidLinesCount++;
                console.warn(`文件 ${fileName} 中包含不符合时间+值格式的行: ${line}`);
              }
            }
          });
          
          // 验证文件格式，如果无效行比例过高，提示错误
          if (totalNonEmptyLines > 0 && invalidLinesCount / totalNonEmptyLines > 0.5) {
            console.error(`文件 ${fileName} 内容格式错误：大多数行不符合时间+值格式（HH:mm:ss:SSS 值）`);
          } else {
            console.log(`成功解析文件 ${fileName}，有效数据点数量: ${fileData.length}`);
          }
          
          // 辅助函数：将时间字符串(HH:mm:ss:SSS)直接转换为毫秒数
          // 注意：这里不计算相对偏移量，直接将时间字符串转换为总毫秒数
          function convertTimeToOffset(timeStr) {
            try {
              // 解析时间格式：HH:mm:ss:SSS
              const [hours, minutes, seconds, milliseconds] = timeStr.split(/[:.]/).map(Number);
              
              // 直接计算总毫秒数
              const totalMilliseconds = 
                hours * 3600000 +     // 小时转毫秒
                minutes * 60000 +     // 分钟转毫秒
                seconds * 1000 +      // 秒转毫秒
                milliseconds;         // 毫秒
              
              return totalMilliseconds;
            } catch (error) {
              console.error('时间解析错误:', error, '时间字符串:', timeStr);
              return 0;
            }
          }
          
          // 按时间排序该文件的数据
          fileData.sort((a, b) => {
            const timeA = a.sysTime || a.time || a.timestamp || 0;
            const timeB = b.sysTime || b.time || b.timestamp || 0;
            return timeA - timeB;
          });
          
          // 根据显示频率过滤数据点
          const filteredData = filterDataByFrequency(fileData);
          
          // 存储该文件的数据
          telemetryDataByFile.value[fileName] = filteredData;
          console.log(`成功读取并解析文件 ${fileName}，原始数据点数量: ${fileData.length}，过滤后数据点数量: ${filteredData.length}`);
        } else {
          console.error(`读取文件 ${fileName} 失败:`, result.error);
          ElMessage.error(`读取文件 ${fileName} 失败: ${result.error}`);
        }
      } catch (error) {
        console.error(`处理文件 ${fileName} 时发生错误:`, error);
        ElMessage.error(`处理文件 ${fileName} 时发生错误`);
      }
    }
  }
  
  console.log("遥测数据解析完成:", Object.keys(telemetryDataByFile.value).length, "个文件,存储在：",telemetryDataByFile.value);
};

// 加载遥测数据
const loadTelemetryData = async () => {
  try {
    // 准备查询参数
    const params = {
      dataId: id,
    };
    const telemetryResult = await telemetryDataListAPI.getTelemetryStoragePath(params);
    console.log("获取遥测数据文件列表结果:", telemetryResult);
    if (telemetryResult && telemetryResult.code === 0) {
      telemetryFiles.value = telemetryResult.data|| [];
      ElMessage.success(`加载了 ${  telemetryFiles.value.length} 个遥测文件`);
    } else {
      throw new Error(result?.msg || '加载遥测文件数据失败');
    }
  } catch (error) {
    console.error("加载遥测文件数据时发生错误:", error);
    ElMessage.error("加载遥测文件数据失败");
  }
};

const gridStyle = computed(() => {
  return {
    display: "grid",
    gridTemplateColumns: `repeat(${windowLayout.value}, 1fr)`,
    gap: "16px",
    minHeight: 0,
    padding: "0",
  };
});

// 图表网格样式 - 与视频网格使用相同的布局参数
const chartGridStyle = computed(() => {
  return {
    display: "grid",
    gridTemplateColumns: `repeat(${windowLayout.value}, 1fr)`,
    gap: "20px",
    padding: "16px",
    overflowY: "auto",
    flex: 1,
    minHeight: 0,
  };
});

const enlargedGridStyle = computed(() => {
  const count = selectedVideos.value.length;

  if (count === 1) {
    return {
      display: "flex",
      alignItems: "stretch",
      justifyContent: "stretch",
      width: "100%",
      height: "100%",
    };
  }

  let columns = 1;
  if (count <= 4) columns = 2;
  else if (count <= 9) columns = 3;
  else columns = 4;

  return {
    display: "grid",
    gridTemplateColumns: `repeat(${columns}, 1fr)`,
    gap: "16px",
  };
});

const enlargedGridClass = computed(() => {
  return selectedVideos.value.length === 1 ? "single-video" : "multi-video";
});

const enlargedItemClass = computed(() => {
  return selectedVideos.value.length === 1 ? "single-video" : "";
});

// 视频选择功能
const onVideoSelect = () => {
  // 复选框变化时的处理
};

const selectAllVideos = () => {
  const totalVideos = localFiles.value.videos.length;
  if (selectedVideos.value.length === totalVideos) {
    selectedVideos.value = [];
  } else {
    selectedVideos.value = Array.from({ length: totalVideos }, (_, i) => i);
  }
};

const enlargeSelectedVideos = () => {
  if (selectedVideos.value.length === 0) return;
  showEnlargedDialog.value = true;
};

const closeEnlargedDialog = () => {
  showEnlargedDialog.value = false;
};

const fullscreenSingleVideo = (videoIndex) => {
  enlargedVideoRefs.value[videoIndex]?.toggleFullscreen?.();
};

// 播放控制功能 - 修改为异步函数以支持await
const togglePlayback = async () => {
  console.log('togglePlayback called, current isPlaying:', isPlaying.value);
  
  // 检查开始时间和结束时间是否有效
  if (!isTimeValid()) {
    ElMessage.warning('开始时间和结束时间不能为空且格式必须正确');
    return;
  }
  
  // 检查是否选择了遥测文件
  if (selectedTelemetryFiles.value.length === 0 && telemetryFiles.value.length > 0) {
    ElMessage.warning('请至少选择一个遥测文件');
    return;
  }
  
  isPlaying.value = !isPlaying.value;
  console.log('new isPlaying value:', isPlaying.value);
  
  // 在点击播放按钮时解析选中的遥测文件内容并生成曲线图
  await parseSelectedTelemetryFiles();

  // 如果用户选择了文件并点击了播放，隐藏选择区域，显示图表区域
  if (selectedTelemetryFiles.value.length > 0) {
    showTelemetrySelection.value = false;
    showTelemetryCharts.value = true;
  }

  // 如果当前时间已经到达末尾，重新开始播放
  if (isPlaying.value && currentPlaybackTime.value >= totalPlaybackTime.value - 0.1) {
    console.log('Resetting to start for replay');
    currentPlaybackTime.value = 0;
    playbackProgress.value = 0;
  }
  
  // 确保播放时从正确的相对时间开始（不是从0开始，而是基于startCollectTime的偏移量）
  if (isPlaying.value && currentPlaybackTime.value === 0) {
    console.log('Starting playback from correct offset');
    // 这里不需要设置具体值，因为我们已经修改了显示逻辑，
    // 显示的时间会基于startCollectTime加上currentPlaybackTime偏移量
  }

  syncAllVideos();
  // 不再需要直接调用seekToTime方法，现在通过props.currentPlaybackTime的响应式特性自动更新图表
  // 这样可以避免重复更新和潜在的初始化问题
};

// 重新选择遥测文件
const reselectTelemetryFiles = () => {
  showTelemetrySelection.value = true;
  showTelemetryCharts.value = false;
  // 如果需要，可以清空已选中的文件
  // selectedTelemetryFiles.value = [];
};

const seekForward = () => {
  const newTime = Math.min(
    currentPlaybackTime.value + 10,
    totalPlaybackTime.value
  );
  seekToTime(newTime);
};

const seekBackward = () => {
  const newTime = Math.max(currentPlaybackTime.value - 10, 0);
  seekToTime(newTime);
};

const seekToTime = (time) => {
  currentPlaybackTime.value = time;
  playbackProgress.value = (time / totalPlaybackTime.value) * 100;
  syncAllVideos();
  
  // 同步所有遥测图表 - 修改为支持多个图表
  // 不再需要直接调用seekToTime方法，通过props.currentPlaybackTime的响应式特性自动更新图表
  // currentPlaybackTime已在函数开头更新，图表会自动响应
};

const onSpeedChange = () => {
  syncAllVideos();
};

// 拖动进度条时，所有视频都 setCurrentTime，短视频超出 duration 后保持最后一帧
const syncAllVideos = () => {
  videoRefs.value.forEach((video) => {
    if (video) {
      const duration = video.getDuration?.() || 0;
      const time = Math.min(currentPlaybackTime.value, duration);
      video.setCurrentTime?.(time);
      video.setPlaybackRate?.(playbackSpeed.value);
      if (isPlaying.value) {
        // 如果当前时间等于或超过视频时长，且正在播放，说明需要重新开始
        if (time >= duration) {
          video.setCurrentTime?.(0);
          video.play?.();
        } else {
          video.play?.();
        }
      } else {
        video.pause?.();
      }
    }
  });
  Object.values(enlargedVideoRefs.value).forEach((video) => {
    if (video) {
      const duration = video.getDuration?.() || 0;
      const time = Math.min(currentPlaybackTime.value, duration);
      video.setCurrentTime?.(time);
      video.setPlaybackRate?.(playbackSpeed.value);
      if (isPlaying.value) {
        // 如果当前时间等于或超过视频时长，且正在播放，说明需要重新开始
        if (time >= duration) {
          video.setCurrentTime?.(0);
          video.play?.();
        } else {
          video.play?.();
        }
      } else {
        video.pause?.();
      }
    }
  });
};

const onVideoTimeUpdate = (time) => {
  if (!isPlaying.value) return;

  // 获取所有视频中最大的当前时间，避免短视频结束后时间回退
  let maxCurrentTime = time;
  videoRefs.value.forEach(video => {
    if (video && video.getCurrentTime) {
      const videoTime = video.getCurrentTime();
      if (videoTime > maxCurrentTime) {
        maxCurrentTime = videoTime;
      }
    }
  });

  currentPlaybackTime.value = maxCurrentTime;
  // 只有在非拖动状态下才更新进度条，避免跳动
  if (!isDragging) {
    // 确保进度条在播放完成时显示100%
    const progress = (maxCurrentTime / totalPlaybackTime.value) * 100;
    playbackProgress.value = Math.min(100, Math.max(0, progress));

    // 如果接近播放完成（99.5%以上），强制设置为100%
    if (progress >= 99.5) {
      playbackProgress.value = 100;
    }
  }
  
  // 同步所有遥测数据图表到当前播放时间 - 每次时间更新都触发数据筛选
  // 使用更安全的方式，通过currentPlaybackTime的响应式特性让图表自动更新，避免直接调用seekToTime
  // 这样图表组件的displayData计算属性会自动根据currentPlaybackTime更新，无需直接调用方法
};

let previewDebounceTimer = null;
let isDragging = false;

const onProgressInput = (value) => {
  isDragging = true;
  // 拖动时不更新 playbackProgress，避免与 onVideoTimeUpdate 冲突
  // 更新当前播放时间，确保UI显示随着拖动变化
  const previewTime = (value / 100) * totalPlaybackTime.value;
  console.log('previewTime:', previewTime);
  currentPlaybackTime.value = previewTime;

  // 拖动时暂停所有视频，避免卡顿
  videoRefs.value.forEach(video => video?.pause?.());
  Object.values(enlargedVideoRefs.value).forEach(video => video?.pause?.());

  // 防抖预览帧：每 200ms 同步一次所有视频 currentTime
  // 注意：遥测数据会通过currentPlaybackTime的响应式更新自动同步，无需直接调用seekToTime
  if (previewDebounceTimer) clearTimeout(previewDebounceTimer);
  previewDebounceTimer = setTimeout(() => {
    videoRefs.value.forEach(video => video?.setCurrentTime?.(previewTime));
    Object.values(enlargedVideoRefs.value).forEach(video => video?.setCurrentTime?.(previewTime));
    
    // 遥测数据通过currentPlaybackTime的响应式更新自动同步到图表
    console.log('Video time synchronized to previewTime:', previewTime);
  }, 200);
};

const onProgressChange = (value) => {
  isDragging = false;
  // 清除防抖定时器
  if (previewDebounceTimer) {
    clearTimeout(previewDebounceTimer);
    previewDebounceTimer = null;
  }

  const newTime = (value / 100) * totalPlaybackTime.value;
  seekToTime(newTime); // 这里会调用 syncAllVideos

  // 松开后恢复播放（如果 isPlaying）
  if (isPlaying.value) {
    videoRefs.value.forEach(video => video?.play?.());
    Object.values(enlargedVideoRefs.value).forEach(video => video?.play?.());
  }
};

// 图表时间变化事件处理 - 现在由主播放控制统一管理，此函数可能不再需要
const onChartTimeChange = (time) => {
  // 注释：由于已移除图表内部播放控制，此函数可能不再被调用
  // seekToTime(time);
};

// 遥测数据播放完成时的处理
const onTelemetryPlaybackComplete = () => {
  // 检查是否所有视频都播放完成
  const allVideosEnded = videoRefs.value.every(video => {
    if (video && video.getDuration && video.getCurrentTime) {
      const duration = video.getDuration();
      const currentTime = video.getCurrentTime();
      return currentTime >= duration - 0.1; // 允许0.1秒的误差
    }
    return false;
  });

  if (allVideosEnded) {
    // 所有视频和遥测数据都播放完成，重置到初始状态
    isPlaying.value = false;
    currentPlaybackTime.value = 0;
    playbackProgress.value = 0;
    syncAllVideos();
    // 重置所有遥测数据到初始状态
    Object.values(historicalChartRefs.value).forEach(chart => {
      if (chart && chart.setCurrentIndex) {
        chart.setCurrentIndex(0);
      }
    });
  }
};

// 视频播放完成时的处理
const onVideoEnded = () => {
  // 检查是否所有视频都播放完成
  const allVideosEnded = videoRefs.value.every(video => {
    if (video && video.getDuration && video.getCurrentTime) {
      const duration = video.getDuration();
      const currentTime = video.getCurrentTime();
      return currentTime >= duration - 0.1; // 允许0.1秒的误差
    }
    return false;
  });

  if (allVideosEnded && isPlaying.value) {
    // 所有视频都播放完成，重置到初始状态
    isPlaying.value = false;
    currentPlaybackTime.value = 0;
    playbackProgress.value = 0;
    syncAllVideos();
    // 重置所有遥测数据到初始状态
    Object.values(historicalChartRefs.value).forEach(chart => {
      if (chart && chart.setCurrentIndex) {
        chart.setCurrentIndex(0);
      }
    });
  }
};

// 保持原有功能
const refreshGrid = () => {};
const maximizeVideo = (i) => {
  videoRefs.value[i]?.toggleFullscreen?.();
};

// getVideoSrc 使用本地视频文件
const getVideoSrc = (index) => {
  // index 从 1 开始，对应视频数组的索引
  const videoIndex = index - 1;
  if (localFiles.value.videos && localFiles.value.videos[videoIndex]) {
    return `file://${localFiles.value.videos[videoIndex].localPath}`;
  }
  return '/test.mp4'; // 默认视频
};

// 获取视频标题
const getVideoTitle = (index) => {
  if (localFiles.value.videos && localFiles.value.videos[index]) {
    return localFiles.value.videos[index].fileName;
  }
  return `视频 ${index + 1}`;
};

// 根据索引获取视频源
const getVideoSrcForIndex = (index) => {
  if (localFiles.value.videos && localFiles.value.videos[index]) {
    // 在 Electron 环境中，需要使用 file:// 协议访问本地文件
    console.log(55555555555555)
    console.log( localFiles.value.videos[index])
    return videoPath.value+localFiles.value.videos[index].accessPath;
   // return `file://${localFiles.value.videos[index].localPath}`;
  }
  return '/test.mp4';
};

const getVideoPoster = (index) => {
  // 灰白色背景，中间显示黑色"视频采集画面"文字
  // 使用更简单的SVG结构确保中文显示正确
  const svg = `<svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
    <rect width="100%" height="100%" fill="#f5f5f5"/>
    <text x="50%" y="50%" font-family="Arial, sans-serif" font-size="18" fill="#333333" text-anchor="middle" dominant-baseline="middle">视频采集画面</text>
  </svg>`;
  return 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg);
};

// 格式化播放时间，支持毫秒显示
const formatPlaybackTime = (seconds) => {
  if (!seconds || isNaN(seconds)) return "00:00:00";
  
  // 转换为毫秒
  const totalMilliseconds = Math.floor(seconds * 1000);
  
  // 计算小时、分钟、秒和毫秒
  const hours = Math.floor(totalMilliseconds / 3600000);
  const mins = Math.floor((totalMilliseconds % 3600000) / 60000);
  const secs = Math.floor((totalMilliseconds % 60000) / 1000);
  const ms = totalMilliseconds % 1000;
  
  // 根据是否有小时来决定返回格式
  if (hours > 0) {
    return `${hours.toString().padStart(2, "0")}:${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
  } else {
    return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
  }
};

// 格式化时间字符串，只显示时分秒毫秒
const formatTimeOnly = (timeString) => {
  if (!timeString) return "00:00:00.000";
  
  try {
    const date = new Date(timeString);
    const hours = date.getHours().toString().padStart(2, '0');
    const minutes = date.getMinutes().toString().padStart(2, '0');
    const seconds = date.getSeconds().toString().padStart(2, '0');
    const milliseconds = Math.floor(date.getMilliseconds() / 10).toString().padStart(2, '0'); // 保留两位毫秒
    
    return `${hours}:${minutes}:${seconds}.${milliseconds}`;
  } catch (error) {
    console.error('时间格式化失败:', error);
    return "00:00:00.000";
  }
};

// 将开始时间与当前播放时间结合，生成实际的播放时间显示
const formatCombinedTime = (startTime, currentTimeInSeconds) => {
  try {
    // 解析开始时间
    const startDate = new Date(startTime);
    
    // 如果开始时间无效，使用默认格式
    if (isNaN(startDate.getTime())) {
      return formatTimeOnly(startTime);
    }
    
    // 计算当前实际时间（开始时间 + 播放偏移量）
    const currentDate = new Date(startDate);
    currentDate.setMilliseconds(currentDate.getMilliseconds() + Math.floor(currentTimeInSeconds * 1000));
    
    // 格式化时间显示（HH:mm:ss.SSS）
    const hours = currentDate.getHours().toString().padStart(2, '0');
    const minutes = currentDate.getMinutes().toString().padStart(2, '0');
    const seconds = currentDate.getSeconds().toString().padStart(2, '0');
    const milliseconds = Math.floor(currentDate.getMilliseconds() / 10).toString().padStart(2, '0') + (Math.floor(currentDate.getMilliseconds() % 10));
    console.log('当前播放时间:', `${hours}:${minutes}:${seconds}.${milliseconds}`);
    return `${hours}:${minutes}:${seconds}.${milliseconds}`;
  } catch (error) {
    console.error('格式化组合时间出错:', error);
    // 出错时回退到原始格式
    return formatTimeOnly(startTime);
  }
};

// 更新总播放时长 - 根据实际视频文件
const updateTotalPlaybackTime = () => {
  if (localFiles.value.videos && localFiles.value.videos.length > 0) {
    // 获取所有视频的最大时长
    const durations = localFiles.value.videos.map((video, index) => {
      const videoRef = videoRefs.value[index];
      return videoRef && videoRef.getDuration ? videoRef.getDuration() : 0;
    });

    const maxDuration = Math.max(...durations);
    if (maxDuration && maxDuration !== totalPlaybackTime.value) {
      totalPlaybackTime.value = maxDuration;
      console.log(`更新总播放时长: ${maxDuration}秒 (${formatPlaybackTime(maxDuration)})`);
    }
  }
};

// 视频加载完成事件
const onVideoLoaded = (index) => {
  console.log(`视频 ${index + 1} 加载完成`);
  // 如果没有从开始/结束时间计算出有效时长，再基于视频文件更新
  if (totalPlaybackTime.value === 0) {
    // 延迟更新总时长，确保所有视频都已加载
    setTimeout(updateTotalPlaybackTime, 500);
  }
};

// 监听视频引用变化，更新总时长
watch(videoRefs, () => {
  // 延迟更新，确保视频已加载
  setTimeout(updateTotalPlaybackTime, 1000);
}, { deep: true });

// 弹窗打开时/refs变化时尝试刷新 duration
watch([showEnlargedDialog, enlargedVideoRefs, selectedVideos], ([show]) => {
  if (show) {
    nextTick(() => {
      setTimeout(updateTotalPlaybackTime, 500);
    });
  }
});

// 监听本地文件变化，自动加载遥测数据和初始化视频状态
watch(localFiles, async (newFiles) => {
  if (newFiles.videos && newFiles.videos.length > 0) {
    initializeVideoStatus();
  }
}, { deep: true });

// 组件挂载时加载数据
onMounted(async () => {
  await loadDataDetail();
  await getVideoList();
  await loadTelemetryData();
});
</script>

<style scoped>
.data-detail {
  height: 100vh;
  display: flex;
  flex-direction: column;
  padding: 16px;
  gap: 16px;
  overflow: hidden;
  background: #f5f5f5;
}
.header-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 0;
  flex-shrink: 0;
}

.data-info {
  display: flex;
  gap: 8px;
  align-items: center;
}

.no-videos {
  text-align: center;
  padding: 60px 40px 60px 40px;
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  border-radius: 12px;
  border: 2px dashed #dee2e6;
  margin: 0;
  min-height: 300px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.no-telemetry {
  text-align: center;
  padding: 40px 30px 40px 30px;
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  border-radius: 12px;
  border: 2px dashed #dee2e6;
  margin: 0;
  min-height: 250px;
  display: flex;
  align-items: center;
  justify-content: center;
}



.empty-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.empty-title {
  color: #495057;
  font-size: 15px;
  font-weight: 600;
  margin: 0;
}

.empty-tip {
  color: #6c757d;
  font-size: 13px;
  margin: 0;
  line-height: 1.4;
  text-align: center;
  max-width: 300px;
}
.title {
  font-size: 18px;
  font-weight: bold;
}
.detail-content-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-height: 0;
  overflow: hidden;
}

.detail-content-area:has(.no-videos) {
  gap: 0;
}
.content-area {
  display: flex;
  gap: 20px;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.video-section {
  flex: 2;
  background: white;
  border-radius: 8px;
  border: 1px solid #e8e8e8;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
.screen-section {
  flex: 1;
  background: white;
  border-radius: 8px;
  border: 1px solid #e8e8e8;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid #f0f0f0;
  flex-shrink: 0;
  background: #fafafa;
}
.section-header h3 {
  margin: 0;
  color: #333;
  font-size: 15px;
  font-weight: 600;
}
.video-info,
.chart-info {
  font-size: 13px;
  color: #666;
  display: flex;
  align-items: center;
}

/* 多图表网格布局 - 基础样式，具体列数通过:style绑定计算属性实现 */
.chart-grid {
  display: grid;
  gap: 20px;
  padding: 16px;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

/* 单个图表项 */
.chart-item {
  background: white;
  border-radius: 8px;
  border: 1px solid #e8e8e8;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 300px;
}

/* 图表项头部 */
.chart-item-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: #fafafa;
  border-bottom: 1px solid #f0f0f0;
}

/* 图表文件名 */
.chart-file-name {
  font-size: 14px;
  font-weight: 500;
  color: #333;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 300px;
}

/* 头部右侧区域 */
.header-right {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* 图表数据点数 */
.chart-data-count {
  font-size: 13px;
  color: #666;
}

/* 图表容器 */
.data-detail.chart-container {
  flex: 1;
  padding: 16px;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.video-item {
  position: relative;
  border: 2px solid #e8e8e8;
  border-radius: 4px;
  overflow: hidden;
  cursor: pointer;
  transition: all 0.2s ease;
  background: #f8f9fa;
  min-height: 0;
}
.video-item:hover {
  border-color: #409eff;
}
.video-item.active {
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}
.video-info-overlay {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
  color: white;
  padding: 4px 8px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.video-title {
  font-size: 11px;
  font-weight: 500;
}
.screen-preview {
  flex: 1;
  padding: 16px;
  min-height: 0;
  overflow: hidden;
}
.screen-container {
  width: 100%;
  height: 100%;
  border: 2px dashed #d9d9d9;
  border-radius: 4px;
  position: relative;
  overflow: hidden;
  transition: all 0.2s ease;
}
.screen-container.has-data {
  border-color: #52c41a;
  border-style: solid;
}
.screen-player {
  position: relative;
  width: 100%;
  height: 100%;
}
.screen-video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
}
.screen-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.3);
}
.play-button {
  width: 64px;
  height: 64px;
  background: rgba(0, 0, 0, 0.6);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  cursor: pointer;
  transition: all 0.3s ease;
}
.play-button:hover {
  background: rgba(0, 0, 0, 0.8);
  transform: scale(1.1);
}
.screen-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #999;
}

/* 遥测文件选择区域样式 */
.file-selection-section {
  background: white;
  border-radius: 8px;
  border: 1px solid #e8e8e8;
  margin-bottom: 16px;
  padding: 16px;
}

.file-selection-section .section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.file-selection-section .section-header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 500;
}

.file-selection-section .file-count {
  color: #606266;
  font-size: 14px;
}

/* 数据网格样式 - 参考DataCollection.vue */
.data-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
}

.data-card {
  border: 1px solid #e8e8e8;
  border-radius: 8px;
  padding: 12px;
  cursor: pointer;
  transition: all 0.3s ease;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  background: white;
}

.data-card:hover {
  border-color: #409eff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.data-card.selected {
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

.card-checkbox {
  flex-shrink: 0;
}

.card-checkbox input[type="checkbox"] {
  display: none;
}

.card-checkbox .custom-checkbox {
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  position: relative;
  cursor: pointer;
  transition: all 0.3s ease;
}

.card-checkbox input[type="checkbox"]:checked + .custom-checkbox {
  background-color: #409eff;
  border-color: #409eff;
}

.card-checkbox input[type="checkbox"]:checked + .custom-checkbox::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 3px;
  width: 6px;
  height: 10px;
  border: solid white;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.card-content {
  flex: 1;
  min-width: 0;
}

.data-name {
  margin: 0 0 4px 0;
  font-size: 14px;
  font-weight: 500;
  color: #303133;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-size {
  margin: 0;
  font-size: 12px;
  color: #909399;
}

/* 播放控制区域按钮布局 */
.playback-controls .control-left {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* 播放按钮样式增强 */
.play-btn {
    background: #409eff !important;
    border-color: #409eff !important;
    color: white !important;
    width: 40px !important;
    height: 40px !important;
    font-size: 24px !important;
    box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
    transition: all 0.3s ease;
  }

.play-btn:hover {
  background: #66b1ff !important;
  border-color: #66b1ff !important;
  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.4);
  transform: translateY(-1px);
}

.play-btn:active {
  transform: translateY(0);
}
.chart-section {
  background: white;
  border-radius: 8px;
  border: 1px solid #e8e8e8;
  min-height: 350px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.chart-section:has(.no-telemetry) {
  height: auto;
  min-height: 280px;
}
.chart-area {
  flex: 1;
  padding: 16px;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding-bottom: 16px;
}

.chart-area:has(.no-telemetry) {
  overflow: visible;
  min-height: 280px;
  padding-bottom: 16px;
}
.chart-area .historical-chart {
  height: 100%;
  min-height: 220px;
}
.playback-section {
  background: white;
  border-radius: 8px;
  border: 1px solid #e8e8e8;
  margin-top: 12px;
  flex-shrink: 0;
  overflow: hidden;
}
.playback-controls {
  display: flex;
  align-items: center;
  padding: 16px 20px;
  gap: 20px;
  background: #fafafa;
  border-radius: 8px;
}
.control-left,
.control-right {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 80px;
}
.control-right {
  justify-content: flex-end;
}
.current-time,
.total-time {
  font-family: "Courier New", monospace;
  font-size: 14px;
  color: #333;
  font-weight: 600;
}
.play-btn {
  background: #409eff !important;
  border-color: #409eff !important;
  color: white !important;
}
.progress-container {
  flex: 1;
  position: relative;
}
.progress-slider {
  --el-slider-runway-bg-color: rgba(0, 0, 0, 0.1);
  --el-slider-main-bg-color: #409eff;
  --el-slider-button-size: 18px;
}
.video-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 8px;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
}
.toolbar-label {
  font-size: 14px;
  color: #333;
  margin-right: 4px;
}
.video-scroll-wrapper {
  max-height: 600px;
  min-height: 180px;
  height: auto;
  overflow-y: auto;
  background: transparent;
  border-radius: 8px;
}

.video-scroll-wrapper:has(.no-videos) {
  max-height: none;
  overflow-y: visible;
  height: auto;
}
.video-grid {
  width: 100%;
  margin: 0 auto;
  min-height: 200px;
  display: grid;
  gap: 16px;
}
.video-card {
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
  min-height: 180px;
  aspect-ratio: 16/10;
  width: 100%;
}
.video-card-topbar {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
  pointer-events: none;
  width: calc(100% - 16px);
}
.video-title {
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  background: rgba(0, 0, 0, 0.45);
  border-radius: 4px;
  padding: 2px 8px;
  pointer-events: auto;
  max-width: calc(100% - 80px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: inline-block;
}
.video-status-text {
  font-weight: bold;
  margin-left: 8px;
  font-size: 15px;
  letter-spacing: 1px;
}
.video-status-text.online {
  color: #21c521;
  text-shadow: 0 0 2px #0a7a0a;
}
.video-status-text.offline {
  color: #ff3b3b;
  text-shadow: 0 0 2px #a10000;
}
.video-card-icons {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 3;
  display: flex;
  gap: 8px;
  pointer-events: auto;
  background: rgba(0, 0, 0, 0.3);
  border-radius: 4px;
  padding: 2px 4px;
}
.video-icon {
  color: #fff;
  font-size: 20px;
  cursor: pointer;
  transition: color 0.2s, transform 0.2s;
  opacity: 0.9;
}
.video-icon:hover {
  color: #ffd700;
  opacity: 1;
  transform: scale(1.18);
}
.video-card-body {
  flex: 1 1 0;
  display: flex;
  align-items: stretch;
  justify-content: stretch;
  padding: 0;
  height: 100%;
}
.video-player {
  width: 100% !important;
  height: 100% !important;
}
.video-container,
.video-container video {
  width: 100% !important;
  height: 100% !important;
  object-fit: cover !important;
}
@media (max-width: 1200px) {
  .content-area {
    flex-direction: column;
    gap: 16px;
  }
  .video-section,
  .screen-section {
    flex: none;
    height: 300px;
  }
  .video-grid {
    grid-template-columns: repeat(2, 1fr) !important;
  }
}
@media (max-width: 768px) {
  .data-detail {
    padding: 12px;
    gap: 12px;
  }
  .video-grid {
    grid-template-columns: 1fr !important;
  }
  .header-bar {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }
}

.video-card.selected {
  border: 2px solid #409eff;
  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
}

.video-checkbox {
  position: absolute;
  bottom: 8px;
  left: 8px;
  border-radius: 4px;
}

.video-checkbox .el-checkbox {
  --el-checkbox-text-color: white;
}

.enlarged-video-dialog {
  --el-dialog-content-font-size: 16px;
}

.fullscreen-dialog {
  --el-dialog-margin-top: 0;
  --el-dialog-bg-color: #000;
}

.fullscreen-dialog .el-dialog {
  margin: 0;
  border-radius: 0;
  background: #000;
}

.fullscreen-dialog .el-dialog__header {
  padding: 12px 20px;
  background: rgba(0, 0, 0, 0.8);
  border-bottom: 1px solid #333;
  position: relative;
}

.fullscreen-dialog .el-dialog__headerbtn {
  position: absolute;
  top: 12px;
  right: 20px;
  z-index: 10;
}

.fullscreen-dialog .el-dialog__headerbtn .el-dialog__close {
  color: #fff;
  font-size: 20px;
  transition: all 0.3s ease;
}

.fullscreen-dialog .el-dialog__headerbtn .el-dialog__close:hover {
  color: #f56c6c;
  transform: scale(1.1);
}

.fullscreen-dialog .el-dialog__body {
  padding: 0;
  height: calc(100vh - 60px);
  background: #000;
  overflow: hidden;
}

.fullscreen-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}

.dialog-title {
  color: white;
  font-size: 18px;
  font-weight: 600;
}



.enlarged-video-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #000;
  overflow: hidden;
}

.enlarged-video-grid {
  flex: 1;
  display: flex;
  overflow: hidden;
}

.enlarged-video-grid.single-video {
  padding: 0;
  align-items: center;
  justify-content: center;
}

.enlarged-video-grid.multi-video {
  padding: 20px;
  overflow: auto;
}

.enlarged-video-item {
  background: #111;
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  border: 1px solid #333;
}

.enlarged-video-item.single-video {
  width: 100%;
  height: 100%;
  border-radius: 0;
  border: none;
  background: #000;
}

.enlarged-video-item.single-video .enlarged-video-header {
  position: absolute;
  top: 20px;
  left: 20px;
  background: rgba(0, 0, 0, 0.7);
  border-radius: 4px;
  z-index: 10;
  border: none;
}

.enlarged-video-header {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  padding: 8px 12px;
  background: #222;
  border-bottom: 1px solid #333;
  font-weight: 600;
  color: white;
}

.enlarged-video-header span {
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
}

.enlarged-video-item .video-player {
  flex: 1;
  height: 100%;
}

.enlarged-video-item.single-video .video-player {
  position: relative;
}

.enlarged-playback-controls {
  display: flex;
  align-items: center;
  padding: 16px 20px;
  gap: 20px;
  background: #fff;
  border-top: 1px solid #e8e8e8;
  flex-shrink: 0;
}

.enlarged-control-left,
.enlarged-control-right {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 160px;
  color: #333;
}

.enlarged-control-right {
  justify-content: flex-end;
}

.enlarged-progress-container {
  flex: 1;
  position: relative;
}

.enlarged-playback-controls .el-button {
  background: #fff;
  border: 1px solid #dcdfe6;
  color: #606266;
}

.enlarged-playback-controls .el-button:hover {
  background: #f5f7fa;
  border-color: #c0c4cc;
}

.enlarged-playback-controls .current-time,
.enlarged-playback-controls .total-time {
  color: #333;
  font-family: monospace;
  font-weight: 500;
}

.enlarged-playback-controls .progress-slider {
  --el-slider-runway-bg-color: #e4e7ed;
  --el-slider-main-bg-color: #409eff;
  --el-slider-button-size: 16px;
}
</style>
